<!DOCTYPE html>
<html lang="zh-CN">

<head>
	<meta http-equiv="content-type" content="text/html;charset=utf-8">
	<meta content="always" name="referrer">
	<meta name="theme-color" content="#2932e1">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<meta name="renderer" content="webkit">
	<link rel="shortcut icon" href="https://www.easyicon.net/api/resizeApi.php?id=580417&size=32" type="image/x-icon">
	<title>梦归处</title>
	<script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
	<link rel="stylesheet" href="http://at.alicdn.com/t/font_1097998_ymj35u0jun.css">
	<style>
		* {
			margin: 0;
			padding: 0;
			box-sizing: border-box;
			/* cursor: url('./img/mouseStyle.png'), auto; */

		}

		body,
		html {
			overflow: hidden;
			height: 100vh;
		}

		a {
			color: #ff6666;
			margin: 15px;
			display: block;
			background-image: linear-gradient(0deg, #3498db, #f47920 10%, #d71345 20%, #f7acbc 30%,
				#ffd400 40%, #3498db 50%, #f47920 60%, #d71345 70%, #f7acbc 80%, #ffd400 90%, #3498db);
			-webkit–moz–ms-background-image: linear-gradient(0deg, #3498db, #f47920 10%, #d71345 20%, #f7acbc 30%,
				#ffd400 40%, #3498db 50%, #f47920 60%, #d71345 70%, #f7acbc 80%, #ffd400 90%, #3498db);
			background-size: 14000% 30000%;
			animation: mymove 120s ease infinite normal;
			-webkit-animation: mymove 120s ease infinite normal;
			-moz-animation: mymove 120s ease infinite normal;
			-webkit–moz–ms-background-clip: text;
			-webkit-background-clip: text;
			/*必需加前缀 -webkit- 才支持这个text值 */
			-webkit-text-fill-color: transparent;
		}

		nav {
			width: 600px;
			padding: 10px 0;
			line-height: 40px;
			text-align: center;
			margin: 0 auto;
			display: flex;
			flex-wrap: wrap;
			padding: 25px;
		}

		main {
			width: 100%;
			height: 60px;
			padding: 10px 0;
			line-height: 40px;
			text-align: center;
			-ms-text-align: center;
		}

		main {
			margin: 0 auto;
		}

		input {
			width: 300px;
			height: 40px;
			border-radius: 40px;
			border: 2px solid #ff6666;
			padding-left: 15px;
			background-color: rgba(255, 255, 255, 0.6);
			font-size: 1em;
			color: #5E6C77;
			background: transparent;
			-webkit-transition: all .100s;
			transition: all .100s;
		}

		input:focus {
			outline: none;
			color: blue;
			border-color: #ff6666;
		}

		input.keyup {
			color: white;
			border-color: white;
			text-shadow: 0 0 .125em white;
			box-shadow: 0 0 .25em white, inset 0 0 .25em white;
		}

		input {
			font-family: "Arial Rounded MT Bold", "Helvetica Rounded", Arial, sans-serif;
		}

		::-webkit-input-placeholder {
			color: #5E6C77;
			text-shadow: 0 0 .125em transparent;
			-webkit-transition: all .25s;
			transition: all .25s;
		}

		input:focus::-webkit-input-placeholder {
			opacity: .5;
		}

		::-moz-placeholder {
			color: #5E6C77;
			text-shadow: 0 0 .125em transparent;
			-webkit-transition: all .25s;
			transition: all .25s;
		}

		input:focus::-moz-placeholder {
			opacity: .5;
		}

		:-ms-input-placeholder {
			color: #5E6C77;
			text-shadow: 0 0 .125em transparent;
			-webkit-transition: all .25s;
			transition: all .25s;
		}

		input:focus:-ms-input-placeholder {
			opacity: .5;
		}


		canvas {
			position: absolute;
			left: 0;
			right: 0;
			top: 0;
			bottom: 0;
			pointer-events: none;
		}

		button {
			width: 60px;
			height: 40px;
			border-radius: 40px;
			outline: none;
			border: none;
			background-color: rgba(255, 102, 102, 0.388);
		}

		h1 {
			color: #ff6666;
			text-align: center;
			line-height: 500px;
			height: 350px;
			user-select: none;
			background-image: linear-gradient(0deg, #3498db, #f47920 10%, #d71345 20%, #f7acbc 30%,
				#ffd400 40%, #3498db 50%, #f47920 60%, #d71345 70%, #f7acbc 80%, #ffd400 90%, #3498db);
			-webkit–moz–ms-background-image: linear-gradient(0deg, #3498db, #f47920 10%, #d71345 20%, #f7acbc 30%,
				#ffd400 40%, #3498db 50%, #f47920 60%, #d71345 70%, #f7acbc 80%, #ffd400 90%, #3498db);
			background-size: 14000% 30000%;
			animation: mymove 120s ease infinite normal;
			-webkit-animation: mymove 120s ease infinite normal;
			-moz-animation: mymove 120s ease infinite normal;
			background-clip: text;
			-webkit-background-clip: text;
			-webkit–moz–ms-background-clip: text;
			/*必需加前缀 -webkit- 才支持这个text值 */
			-webkit-text-fill-color: transparent;
		}

		body {
			background-color: rgba(0, 0, 0, .3);
			background: url(img/gc.jpg) no-repeat center center/100% auto;
			/* background-position: 0 -137px; */
		}

		@keyframes mymove {
			0% {
				background-position: 0% 0%;
			}

			50% {
				background-position: 50% 100%;
			}

			100% {
				background-position: 100% 0%;
			}
		}

		/* main {
			position: fixed;
			z-index: 999;
			top: 35%;
			left: 0;
			right: 0;
			margin: 0 auto;
		}

		nav {
			position: fixed;
			z-index: 998;
			top: 45%;
			left: 0;
			right: 0;
			margin: 0 auto;
		} */
	</style>
</head>

<body>
	<h1>梦归处</h1>
	<!-- 时钟 废弃 -->
	<!-- <h1>
		<canvas width="800" height="400" id="tit">
			<p class="nope">No canvas, no particles</p>
		</canvas>
	</h1> -->
	<!-- <header>
		<h1>Particle Clock</h1>
		<div id="about">
			<a href="#" id="toggle-options"></a>
			<ul id="options">
				<li><a href="#" id="quivers" class="">Quiver</a></li>
				<li><a href="#" id="gradient" class="on">Gradient</a></li>
				<li><a href="#" id="color" class="on">Colorize</a></li>
				<li><a href="#" id="valentineify" class="">Valentine-ify</a></li>
				<li class="group"><span>Mouse down: explode and repel</span></li>
				<li><span>Mouse down + shift: explode and attract</span></li>
				<li><span>Arrow Up: increase particle size</span></li>
				<li class="group"><span>Sorry about your CPU</span></li>
				<li><span id="fps"></span></li>
			</ul>
		</div>
	</header> -->
	<!-- 搜索 -->
	<main>
		<div class="sousuobox">
			<input type="text" placeholder="(/^ω^)/" style="outline: none">
			<button onclick="sousou()">搜索</button>
			<!-- <button>搜索</button> -->
		</div>
	</main>
	<!-- 导航 -->
	<nav>
	</nav>
</body>
<script type="text/javascript" charset="utf-8">
	// 获取搜索框内容
	let str = "";
	$(":text").focus();

	$(":text").change(function () {
		str = $(this).val();
	});
	// 判断按键是否为回车如果是执行搜索
	window.onkeydown = function (e) {
		let code = e.keyCode;
		if (code == 13) {
			$(":text").blur();
			$("button").click();
		}
	}
	// 搜索函数
	function sousou() {
		if (str == "") {
			return;
		}
		let sou = "https://www.baidu.com/s?ie=UTF-8&wd=" + str;
		window.open(sou);
	}

	// 鼠标移动特效
	function RGB() {
		let r = Math.floor(Math.random() * 255);
		let g = Math.floor(Math.random() * 255);
		let b = Math.floor(Math.random() * 255);
		return `rgb(${r},${g},${b})`
	}
	function move(e) {
		let mouseX = e.clientX;
		let mouseY = e.clientY;
		if (mouseX < 10 || mouseY < 10) {
			return;
		}
		let bigchi = document.createElement("i");
		bigchi.className = "iconfont";
		bigchi.classList.add("icon-fengye")
		bigchi.style.left = mouseX + "px";
		bigchi.style.top = mouseY + "px";
		bigchi.style.position = "absolute";
		bigchi.style.pointerEvents = "none"
		bigchi.style.zIndex = 99;
		// bigchi.style.backgroundColor = "red";
		bigchi.style.color = RGB()
		if (bigchi.style.left == 0 && bigchi.style.top == 0) {
			return;
		}
		$("body").append(bigchi);
		function Z() { $(bigchi).animate({ left: mouseX - 10 - (Math.random() * 20), top: mouseY - 15 - (Math.random() * 20) }, 300, function () { this.remove() }) }
		function F() { $(bigchi).animate({ left: mouseX + 10 + (Math.random() * 20), top: mouseY - 15 - (Math.random() * 20) }, 300, function () { this.remove() }) }
		Math.random() > 0.5 ? Z() : F();
	}

	// $(".bigbox").css({ "width": innerWidth, "height": innerHeight, "position": "fixed", "left": 0, "top": 0, "z-index": "0" }).on("mousemove", function (e) {
	// 	move(e);
	// 	event.stopPropagation();
	// })
	$("body").on("mousemove", function (e) {
		move(e);
		event.stopPropagation();
	})
</script>
<!-- <script>
	function fuckyou() {
		window.close(); //关闭当前窗口(防抽)  
		window.location = "about:blank"; //将当前窗口跳转置空白页  
	}
	function ck() {
		console.profile();
		console.profileEnd();
		//我们判断一下profiles里面有没有东西，如果有，肯定有人按F12了，没错！！  
		if (console.clear) { console.clear() };
		if (typeof console.profiles == "object") {
			return console.profiles.length > 0;
		}
	}
	function hehe() {
		if ((window.console && (console.firebug || console.table && /firebug/i.test(console.table()))) || (typeof opera == 'object' && typeof opera.postError == 'function' && console.profile.length > 0)) {
			fuckyou();
		}
		if (typeof console.profiles == "object" && console.profiles.length > 0) {
			fuckyou();
		}
	}
	hehe();
	window.onresize = function () {
		if ((window.outerHeight - window.innerHeight) > 200 | (window.outerWidth - window.innerWidth) > 200)
			//判断当前窗口内页高度和窗口高度，如果差值大于200，那么呵呵  
			fuckyou();
	}
</script> -->
<script>

	var MAX_LIFE = 50;
	var canvas = document.querySelector('canvas');
	var input = document.querySelector('input');
	var field = {}
	var hasFocus = false;
	var caret = document.createElement('span');
	caret.style.cssText = document.defaultView.getComputedStyle(input, '').cssText;
	caret.style.position = 'absolute';
	caret.style.left = 0;
	caret.style.top = 0;
	caret.style.width = 'auto';
	caret.style.visibility = 'hidden';
	document.body.appendChild(caret);

	function reposition() {
		field = input.getBoundingClientRect();
	}
	window.onload = reposition;
	window.onresize = reposition;
	reposition();

	input.onfocus = function () {
		hasFocus = true
	}
	input.onblur = function () {
		hasFocus = false
	}

	function rain() {

	}

	function burst(intensity) {

		var behavior = [
			this.behavior.cohesion(),
			this.behavior.move()
		];

		var size = .75;
		var force = .7;
		var lifeMin = 0;
		var progress = Math.min(field.width, caret.offsetWidth) / field.width;
		var offset = field.left + (field.width * progress);
		var rangeMin = Math.max(field.left, offset - 30);
		var rangeMax = Math.min(field.right, offset + 10);

		this.spray(intensity, function () {
			return [
				null, null,
				Vector.create(
					Random.between(rangeMin + 10, rangeMax - 20),
					Random.between(field.top + 15, field.bottom - 15)
				),
				Vector.random(force),
				size + Math.random(),
				Random.between(lifeMin, 0), behavior
			]
		});

		// top edge
		this.spray(intensity * .5, function () {
			return [
				null, null,
				Vector.create(
					Random.between(rangeMin, rangeMax),
					field.top
				),
				Vector.random(force),
				size + Math.random(),
				Random.between(lifeMin, 0), behavior
			]
		});

		// bottom edge
		this.spray(intensity * .5, function () {
			return [
				null, null,
				Vector.create(
					Random.between(rangeMin, rangeMax),
					field.top + field.height
				),
				Vector.random(force),
				size + Math.random(),
				Random.between(lifeMin, 0), behavior
			]
		});

		// left edge
		if (input.value.length === 1) {

			this.spray(intensity * 2, function () {
				return [
					null, null,
					Vector.create(
						field.left,
						Random.between(field.top, field.bottom)
					),
					Vector.random(force),
					size + Math.random(),
					Random.between(lifeMin, 0), behavior
				]
			});
		}

		// right edge
		if (rangeMax == field.right) {

			this.spray(intensity * 2, function () {
				return [
					null, null,
					Vector.create(
						field.right,
						Random.between(field.top, field.bottom)
					),
					Vector.random(force),
					size + Math.random(),
					Random.between(lifeMin, 0), behavior
				]
			});

		}

	}

	// start particle simulation
	simulate(
		'2d', {
			init: function () {

			},
			tick: function (particles) {

				if (!particles) {
					return;
				}

				particles.forEach(function (p) {

					if (p.life > MAX_LIFE) {
						this.destroy(p);
					}

				});

			},
			beforePaint: function () {
				this.clear();
			},
			paint: function (particle) {

				var p = particle.position;
				var s = particle.size;
				var o = 1 - (particle.life / MAX_LIFE);

				this.paint.circle(p.x, p.y, s, 'rgba(255,255,255,' + o + ')');
				this.paint.circle(p.x, p.y, s + 2, 'rgba(231,244,255,' + (o * .25) + ')');

			},
			afterPaint: function () {
				// nothing
			},
			action: function (x, y) {

				caret.textContent = input.value;

				burst.call(this, 10);

				input.classList.add('keyup');
				setTimeout(function () {
					input.classList.remove('keyup')
				}, 100);

			}
		}
	);

	// "simulate" particle simulation logic
	/**
	 * Constants
	 */
	PI_2 = Math.PI / 2;
	PI_180 = Math.PI / 180;

	/**
	 * Random
	 */
	var Random = {
		between: function (min, max) {
			return min + (Math.random() * (max - min));
		}
	}

	/**
	 * 2D Vector Class
	 */
	function Vector(x, y) {
		this._x = x || 0;
		this._y = y || 0;
	}

	Vector.create = function (x, y) {
		return new Vector(x, y);
	};

	Vector.add = function (a, b) {
		return new Vector(a.x + b.x, a.y + b.y);
	};

	Vector.subtract = function (a, b) {
		return new Vector(a.x - b.x, a.y - b.y);
	};

	Vector.random = function (range) {
		var v = new Vector();
		v.randomize(range);
		return v;
	};

	Vector.distanceSquared = function (a, b) {
		var dx = a.x - b.x;
		var dy = a.y - b.y;
		return dx * dx + dy * dy;
	};

	Vector.distance = function (a, b) {
		var dx = a.x - b.x;
		var dy = a.y - b.y;
		return Math.sqrt(dx * dx + dy * dy);
	};

	Vector.prototype = {
		get x() {
			return this._x;
		},
		get y() {
			return this._y;
		},
		set x(value) {
			this._x = value;
		},
		set y(value) {
			this._y = value;
		},
		get magnitudeSquared() {
			return this._x * this._x + this._y * this._y;
		},
		get magnitude() {
			return Math.sqrt(this.magnitudeSquared);
		},
		get angle() {
			return Math.atan2(this._y, this._x) * 180 / Math.PI;
		},
		clone: function () {
			return new Vector(this._x, this._y);
		},
		add: function (v) {
			this._x += v.x;
			this._y += v.y;
		},
		subtract: function (v) {
			this._x -= v.x;
			this._y -= v.y;
		},
		multiply: function (value) {
			this._x *= value;
			this._y *= value;
		},
		divide: function (value) {
			this._x /= value;
			this._y /= value;
		},
		normalize: function () {
			var magnitude = this.magnitude;
			if (magnitude > 0) {
				this.divide(magnitude);
			}
		},
		limit: function (treshold) {
			if (this.magnitude > treshold) {
				this.normalize();
				this.multiply(treshold);
			}
		},
		randomize: function (amount) {
			amount = amount || 1;
			this._x = amount * 2 * (-.5 + Math.random());
			this._y = amount * 2 * (-.5 + Math.random());
		},
		rotate: function (degrees) {
			var magnitude = this.magnitude;
			var angle = ((Math.atan2(this._x, this._y) * PI_HALF) + degrees) * PI_180;
			this._x = magnitude * Math.cos(angle);
			this._y = magnitude * Math.sin(angle);
		},
		flip: function () {
			var temp = this._y;
			this._y = this._x;
			this._x = temp;
		},
		invert: function () {
			this._x = -this._x;
			this._y = -this._y;
		},
		toString: function () {
			return this._x + ', ' + this._y;
		}
	}

	/**
	 * Particle Class
	 */
	function Particle(id, group, position, velocity, size, life, behavior) {

		this._id = id || 'default';
		this._group = group || 'default';

		this._position = position || new Vector();
		this._velocity = velocity || new Vector();
		this._size = size || 1;
		this._life = Math.round(life || 0);

		this._behavior = behavior || [];

	}

	Particle.prototype = {
		get id() {
			return this._id;
		},
		get group() {
			return this._group;
		},
		get life() {
			return this._life;
		},
		get size() {
			return this._size;
		},
		set size(size) {
			this._size = size;
		},
		get position() {
			return this._position;
		},
		get velocity() {
			return this._velocity;
		},
		update: function (stage) {

			this._life++;

			var i = 0;
			var l = this._behavior.length;

			for (; i < l; i++) {
				this._behavior[i].call(stage, this);
			}

		},
		toString: function () {
			return 'Particle(' + this._id + ') ' + this._life + ' pos: ' + this._position + ' vec: ' + this._velocity;
		}
	}

	// setup DOM
	function simulate(dimensions, options) {

		// private vars
		var particles = [];
		var destroyed = [];
		var update = update || function () { };
		var stage = stage || function () { };
		var canvas;
		var context;

		if (!options) {
			console.error('"options" object must be defined');
			return;
		}

		if (!options.init) {
			console.error('"init" function must be defined');
			return;
		}

		if (!options.paint) {
			console.error('"paint" function must be defined');
			return;
		}

		if (!options.tick) {
			options.tick = function () { };
		}

		if (!options.beforePaint) {
			options.beforePaint = function () { };
		}

		if (!options.afterPaint) {
			options.afterPaint = function () { };
		}

		if (!options.action) {
			options.action = function () { };
		}

		if (document.readyState === 'interactive') {
			setup();
		} else {
			document.addEventListener('DOMContentLoaded', setup);
		}

		// resizes canvas to fit window dimensions
		function fitCanvas() {
			canvas.width = window.innerWidth;
			canvas.height = window.innerHeight;
		}

		// create canvas for drawing
		function setup() {

			// create
			canvas = document.createElement('canvas');
			document.body.appendChild(canvas);

			// correct canvas size on window resize
			window.addEventListener('resize', fitCanvas);

			// go
			go();
		}

		// canvas has been attached, let's go!
		function go() {

			// set initial canvas size
			fitCanvas();

			// get context for drawing
			context = canvas.getContext(dimensions);

			// simulation update loop
			function act() {

				// update particle states
				var i = 0;
				var l = particles.length;
				var p;
				for (; i < l; i++) {
					particles[i].update(this);
				}

				// clean destroyed particles
				while (p = destroyed.pop()) {

					do {

						// has not been found in destroyed array?
						if (p !== particles[i]) {
							continue;
						}

						// remove particle
						particles.splice(i, 1);

					} while (i-- >= 0)
				}

				// repaint context
				options.beforePaint.call(this);

				// repaint particles
				i = 0;
				l = particles.length;
				for (; i < l; i++) {
					options.paint.call(this, particles[i]);
				}

				// after particles have been painted
				options.afterPaint.call(this);
			}

			function tick() {

				// call update method, this allows for inserting particles later on
				options.tick.call(this, particles);

				// update particles here
				act();

				// on to the next frame
				window.requestAnimationFrame(tick);

			}

			/**
			 * API
			 **/
			function clear() {
				context.clearRect(0, 0, canvas.width, canvas.height);
			}

			function destroy(particle) {
				destroyed.push(particle);
			}

			function add(id, group, position, velocity, size, life, behavior) {
				particles.push(new Particle(id, group, position, velocity, size, life, behavior));
			}

			function spray(amount, config) {
				var i = 0;
				for (; i < amount; i++) {
					add.apply(this, config());
				}
			}

			function debug(particle) {
				this.paint.circle(
					particle.position.x,
					particle.position.y,
					particle.size,
					'rgba(255,0,0,.75)'
				);
				context.beginPath();
				context.moveTo(particle.position.x, particle.position.y);
				context.lineTo(particle.position.x + (particle.velocity.x * 10), particle.position.y + (particle.velocity.y * 10));
				context.strokeStyle = 'rgba(255,0,0,.1)';
				context.stroke();
				context.closePath();
			};

			this.clear = clear;
			this.destroy = destroy;
			this.add = add;
			this.spray = spray;
			this.debug = debug;

			this.paint = {
				circle: function (x, y, size, color) {
					context.beginPath();
					context.arc(x, y, size, 0, 2 * Math.PI, false);
					context.fillStyle = color;
					context.fill();
				},
				square: function (x, y, size, color) {
					context.beginPath();
					context.rect(x - (size * .5), y - (size * .5), size, size);
					context.fillStyle = color;
					context.fill();
				}
			}

			this.behavior = {
				cohesion: function (range, speed) {
					range = Math.pow(range || 100, 2);
					speed = speed || .001;
					return function (particle) {

						var center = new Vector();
						var i = 0;
						var l = particles.length;
						var count = 0;

						if (l <= 1) {
							return;
						}

						for (; i < l; i++) {

							// don't use self in group
							if (particles[i] === particle || Vector.distanceSquared(particles[i].position, particle.position) > range) {
								continue;
							}

							center.add(Vector.subtract(particles[i].position, particle.position));
							count++;
						}

						if (count > 0) {

							center.divide(count);

							center.normalize();
							center.multiply(particle.velocity.magnitude);

							center.multiply(.05);
						}

						particle.velocity.add(center);

					}
				},
				separation: function (distance) {

					var distance = Math.pow(distance || 25, 2);

					return function (particle) {

						var heading = new Vector();
						var i = 0;
						var l = particles.length;
						var count = 0;
						var diff;

						if (l <= 1) {
							return;
						}

						for (; i < l; i++) {

							// don't use self in group
							if (particles[i] === particle || Vector.distanceSquared(particles[i].position, particle.position) > distance) {
								continue;
							}

							// stay away from neighbours
							diff = Vector.subtract(particle.position, particles[i].position);
							diff.normalize();

							heading.add(diff);
							count++;
						}

						if (count > 0) {

							// get average
							heading.divide(count);

							// make same length as current velocity (so particle won't speed up)
							heading.normalize();
							heading.multiply(particle.velocity.magnitude);

							// limit force to make particle movement smoother
							heading.limit(.1);
						}

						particle.velocity.add(heading);

					}
				},
				alignment: function (range) {
					range = Math.pow(range || 100, 2);
					return function (particle) {

						var i = 0;
						var l = particles.length;
						var count = 0;
						var heading = new Vector();

						if (l <= 1) {
							return;
						}

						for (; i < l; i++) {

							// don't use self in group also don't align when out of range
							if (particles[i] === particle || Vector.distanceSquared(particles[i].position, particle.position) > range) {
								continue;
							}

							heading.add(particles[i].velocity);
							count++;
						}

						if (count > 0) {

							heading.divide(count);
							heading.normalize();
							heading.multiply(particle.velocity.magnitude);

							// limit
							heading.multiply(.1);

						}

						particle.velocity.add(heading);

					}
				},
				move: function () {
					return function (particle) {
						particle.position.add(particle.velocity);

						// handle collisions?

					}
				},
				eat: function (food) {
					food = food || [];
					return function (particle) {

						var i = 0;
						var l = particles.length;
						var prey;

						for (; i < l; i++) {

							prey = particles[i];

							// can't eat itself, also, needs to be tasty
							if (prey === particle || food.indexOf(prey.group) === -1) {
								continue;
							}

							// calculate force vector
							if (Vector.distanceSquared(particle.position, neighbour.position) < 2 && particle.size >= neighbour.size) {
								particle.size += neighbour.size;
								destroy(neighbour);
							}

						}
					}
				},
				force: function (x, y) {
					return function (particle) {
						particle.velocity.x += x;
						particle.velocity.y += y;
					}
				},
				limit: function (treshold) {
					return function (particle) {
						particle.velocity.limit(treshold);
					}
				},
				attract: function (forceMultiplier, groups) {
					forceMultiplier = forceMultiplier || 1;
					groups = groups || [];
					return function (particle) {

						// attract other particles
						var totalForce = new Vector(0, 0);
						var force = new Vector(0, 0);
						var i = 0;
						var l = particles.length;
						var distance;
						var pull;
						var attractor;
						var grouping = groups.length;

						for (; i < l; i++) {

							attractor = particles[i];

							// can't be attracted by itself or mismatched groups
							if (attractor === particle || (grouping && groups.indexOf(attractor.group) === -1)) {
								continue;
							}

							// calculate force vector
							force.x = attractor.position.x - particle.position.x;
							force.y = attractor.position.y - particle.position.y;
							distance = force.magnitude;
							force.normalize();

							// the bigger the attractor the more force
							force.multiply(attractor.size / distance);

							totalForce.add(force);
						}

						totalForce.multiply(forceMultiplier);

						particle.velocity.add(totalForce);
					}
				},
				wrap: function (margin) {
					return function (particle) {

						// move around when particle reaches edge of screen
						var position = particle.position;
						var radius = particle.size * .5;

						if (position.x + radius > canvas.width + margin) {
							position.x = radius;
						}

						if (position.y + radius > canvas.height + margin) {
							position.y = radius;
						}

						if (position.x - radius < -margin) {
							position.x = canvas.width - radius;
						}

						if (position.y - radius < -margin) {
							position.y = canvas.height - radius;
						}

					}
				},
				reflect: function () {

					return function (particle) {

						// bounce from edges
						var position = particle.position;
						var velocity = particle.velocity;
						var radius = particle.size * .5;

						if (position.x + radius > canvas.width) {
							velocity.x = -velocity.x;
						}

						if (position.y + radius > canvas.height) {
							velocity.y = -velocity.y;
						}

						if (position.x - radius < 0) {
							velocity.x = -velocity.x;
						}

						if (position.y - radius < 0) {
							velocity.y = -velocity.y;
						}
					}

				},
				edge: function (action) {
					return function (particle) {

						var position = particle.position;
						var velocity = particle.velocity;
						var radius = particle.size * .5;

						if (position.x + radius > canvas.width) {
							action(particle);
						}

						if (position.y + radius > canvas.height) {
							action(particle);
						}

						if (position.x - radius < 0) {
							action(particle);
						}

						if (position.y - radius < 0) {
							action(particle);
						}
					}
				}
			}

			// public
			Object.defineProperties(this, {
				'particles': {
					get: function () {
						return particles;
					}
				},
				'width': {
					get: function () {
						return canvas.width;
					}
				},
				'height': {
					get: function () {
						return canvas.height;
					}
				},
				'context': {
					get: function () {
						return context;
					}
				}
			});

			// call init method so the scene can be setup
			options.init.call(this)

			// start ticking
			tick();

			// start listening to events
			var self = this;
			document.addEventListener('keyup', function (e) {
				options.action.call(self, e.pageX, e.pageY);
			});

		}

	};
</script>
<!-- 时钟canvas  废弃 -->
<!-- <script>
	var Clock = (function () {

		// private variables
		var canvas, // canvas element
			ctx, // canvas context
			bgGrad = true, // background gradient flag
			gradient, // gradient (background)
			height = 400, // canvas height
			key = { up: false, shift: false }, // key presses
			particles = [], // particle array
			particleColor = 'hsla(0, 0%, 100%, 0.3)', // particle color
			mouse = { x: 0, y: 0 }, // position of mouse / touch
			press = false, // pressed flag
			quiver = false, // quiver flag
			text, // the text to copy pixels from
			textSize = 140, // (initial) textsize
			valentine = false, // valentine-ify it for a bit?
			msgTime = 100, // time to show a message before returning to clock
			updateColor = true, // update color of gradient / particles with time?
			width = 800; // canvas width

		// Constants
		var FRAME_RATE = 20, // frames per second target
			MIN_WIDTH = 800, // minimum width of canvas
			MIN_HEIGHT = 400, // minimum height of canvas
			PARTICLE_NUM = 600, // (max) number of particles to generate
			RADIUS = Math.PI * 2; // radius of particle

		var defaultStyles = function () {
			textSize = 140;
			// particle color
			particleColor = 'hsla(0, 0%, 100%, 0.3)';

			// color stops
			var gradientStops = {
				0: '#333333',
				0.5: '#222222'
			};

			// create gradient
			setGradient(gradientStops);
		};

		var draw = function (p) {
			ctx.fillStyle = particleColor;
			ctx.beginPath();
			ctx.arc(p.x, p.y, p.size, 0, RADIUS, true);
			ctx.closePath();
			ctx.fill();
		};

		var explode = function () {
			for (var i = 0, l = particles.length; i < l; i++) {
				var p = particles[i];

				if (p.inText) {

					var ax = mouse.x - p.px,
						ay = mouse.y - p.py,
						angle = Math.atan2(ay, ax),
						polarity,
						C = Math.cos(angle),
						S = Math.sin(angle);

					// change polarity
					// attract particles if mouse pressed, repel if shift + mousedown
					polarity = (key.shift === true) ? -1 : 1;

					p.x += polarity * (Math.pow((C - 1), 2) - 1) + p.velocityX * p.delta;
					p.y += polarity * (Math.pow((S - 1), 2) - 1) + p.velocityY * p.delta;

					// set previous positions
					p.px = p.x;
					p.py = p.y;

					draw(p);
				}
			}
		};

		var getTime = function (amPM) {
			var date = new Date(),
				hours = date.getHours(),
				timeOfDay = '';

			if (amPM) {
				hours = (hours > 12) ? hours -= 12 : hours;
				hours = (hours == 0) ? 12 : hours;
			} else {
				hours = pad(hours);
			}

			var minutes = pad(date.getMinutes());
			var seconds = pad(date.getSeconds());
			return {
				hours: hours,
				minutes: minutes,
				seconds: seconds,
				timeString: hours + " : " + minutes + " : " + seconds
			};
		};

		// animation loop
		var loop = function () {

			// clear out text
			ctx.clearRect(0, 0, width, height);

			var time = getTime(true);

			textSize = 140;

			// draw text on canvas
			if (valentine === true) {
				if (msgTime > 0) {
					textSize = 180;
					text = '?';
					msgTime--;
				} else {
					text = time.timeString;
				}
				// valentine-ify it by setting hue to pink
				setStyles(300);

			} else if (updateColor === true && bgGrad === true) {
				// changing color with time
				// @TODO: come up with something better, this is a hacky implementation
				var color = time.hours + time.minutes + time.seconds;
				setStyles(color);
				text = time.timeString;
			} else {
				defaultStyles();
				text = time.timeString;
			}

			ctx.fillStyle = "rgb(255, 255, 255)";
			ctx.textBaseline = "middle";
			ctx.font = textSize + "px 'Avenir', 'Helvetica Neue', 'Arial', 'sans-serif'";
			ctx.fillText(text, (width - ctx.measureText(text).width) * 0.5, height * 0.5);

			// copy pixels
			var imgData = ctx.getImageData(0, 0, width, height);

			// clear canvas, again
			ctx.clearRect(0, 0, width, height);

			if (bgGrad === true) {
				// draw gradient
				ctx.fillStyle = gradient;
				ctx.fillRect(0, 0, width, height);
			}

			if (press === false) {
				// reset particles
				for (var i = 0, l = particles.length; i < l; i++) {
					var p = particles[i];
					p.inText = false;
				}
				particleText(imgData);
			} else {
				explode();
			}
			FPS.update('fps');
		};

		var pad = function (number) {
			return ('0' + number).substr(-2);
		};

		var particleText = function (imgData) {

			var pxls = [];
			for (var w = width; w > 0; w -= 6) {
				for (var h = 0; h < width; h += 6) {
					var index = (w + h * (width)) * 4;
					if (imgData.data[index] > 10) {
						pxls.push([w, h]);
					}
				}
			}

			var count = pxls.length;
			for (var i = 0; i < pxls.length && i < particles.length; i++) {
				try {
					var p = particles[i],
						X,
						Y;

					if (quiver) {
						X = (pxls[count - 1][0]) - (p.px + Math.random() * 5);
						Y = (pxls[count - 1][1]) - (p.py + Math.random() * 5);
					} else {
						X = (pxls[count - 1][0]) - p.px;
						Y = (pxls[count - 1][1]) - p.py;
					}

					// tangent
					var T = Math.sqrt(X * X + Y * Y);

					// arctangent
					var A = Math.atan2(Y, X);

					// cosine
					var C = Math.cos(A);

					// sine
					var S = Math.sin(A);

					// set new postition
					p.x = p.px + C * T * p.delta;
					p.y = p.py + S * T * p.delta;

					// set previous positions
					p.px = p.x;
					p.py = p.y;

					p.inText = true;

					// draw the particle
					draw(p);

					if (key.up === true) {
						p.size += 0.3;
					} else {
						var newSize = p.size - 0.5;
						if (newSize > p.origSize && newSize > 0) {
							p.size = newSize;
						} else {
							p.size = m.origSize;
						}
					}
				} catch (e) {
					//console.log(e);
				}
				count--;
			}
		};

		var setCoordinates = function (e) {
			if (e.offsetX) {
				return { x: e.offsetX, y: e.offsetY }; // use offset if available
			} else if (e.layerX) {
				return { x: e.layerX, y: e.layerY }; // firefox... make sure to position the canvas
			} else {
				// iOS. Maybe others too?
				return { x: e.pageX - canvas.offsetLeft, y: e.pageY - canvas.offsetTop };
			}
		};

		// set dimensions of canvas
		var setDimensions = function () {
			width = Math.max(window.innerWidth, MIN_WIDTH);
			height = Math.max(window.innerHeight, MIN_HEIGHT);

			// Resize the canvas
			canvas.width = width;
			canvas.height = height;

			canvas.style.position = 'absolute';
			canvas.style.left = '0px';
			canvas.style.top = '0px';
		};

		var setGradient = function (gradientStops) {

			// create gradient
			gradient = ctx.createRadialGradient(width / 2, height / 2, 0, width / 2, height / 2, width);

			// iterate through colorstops
			for (var position in gradientStops) {
				var color = gradientStops[position];
				gradient.addColorStop(position, color);
			}
		};

		var setStyles = function (hue) {
			// color stops
			var gradientStops = {
				0: 'hsl(' + hue + ', 100%, 100%)',
				0.5: 'hsl(' + hue + ', 10%, 50%)'
			};

			// change particle color
			particleColor = 'hsla(' + hue + ', 10%, 50%, 0.3)';

			// create gradient
			setGradient(gradientStops);
		};

		/** 
		 * Public Methods
		 */
		return {

			init: function (canvasID) {

				canvas = document.getElementById(canvasID);
				// make sure canvas exists and that the browser understands it
				if (canvas === null || !canvas.getContext) {
					return;
				}
				// set context
				ctx = canvas.getContext("2d");

				// set dimensions
				setDimensions();

				// ui
				this.ui();

				for (var i = 0; i < PARTICLE_NUM; i++) {
					particles[i] = new Particle(canvas);
				}

				// show FPS
				FPS.initialize(canvas, 'fps');

				// set defaults
				defaultStyles();

				// let's do this
				setInterval(loop, FRAME_RATE);

			},

			ui: function () {

				// UI: buttons and events
				var toggleOptions = document.getElementById('toggle-options'),
					options = document.getElementById('options'),
					onMsg = '[-] Hide Options',
					offMsg = '[+] Show Options',
					quiverBtn = document.getElementById('quivers'),
					gradientBtn = document.getElementById('gradient'),
					valentineifyBtn = document.getElementById('valentineify'),
					colorBtn = document.getElementById('color');

				toggleOptions.innerHTML = offMsg;

				/**
				 * Events
				 */
				toggleOptions.addEventListener('click', function (e) {
					e.preventDefault();
					if (options.className === 'on') {
						options.className = '';
						toggleOptions.innerHTML = offMsg;
					} else {
						options.className = 'on';
						toggleOptions.innerHTML = onMsg;
					}
				}, false);

				quiverBtn.addEventListener('click', function (e) {
					e.preventDefault();
					if (quiverBtn.className === 'on') {
						quiverBtn.className = '';
						quiver = false;
					} else {
						quiverBtn.className = 'on';
						quiver = true;
					}
				}, false);

				gradientBtn.addEventListener('click', function (e) {
					e.preventDefault();
					if (gradientBtn.className === 'on') {
						gradientBtn.className = '';
						bgGrad = false;
					} else {
						gradientBtn.className = 'on';
						bgGrad = true;
					}
				}, false);

				valentineifyBtn.addEventListener('click', function (e) {
					e.preventDefault();
					if (valentineifyBtn.className === 'on') {
						valentineifyBtn.className = '';
						valentine = false;
						msgTime = 0;
					} else {
						valentineifyBtn.className = 'on';
						msgTime = 60;
						valentine = true;
					}
				}, false);

				colorBtn.addEventListener('click', function (e) {
					e.preventDefault();
					if (colorBtn.className === 'on') {
						colorBtn.className = '';
						updateColor = false;
					} else {
						colorBtn.className = 'on';
						updateColor = true;
					}
				}, false);

				document.addEventListener('keydown', function (e) {
					switch (e.keyCode) {
						case 16: // shift
							key.shift = true;
							e.preventDefault();
							break;
						case 38: // up key
							key.up = true;
							e.preventDefault();
							break;
					}
				}, false);

				document.addEventListener('keyup', function (e) {
					switch (e.keyCode) {
						case 16: // shift
							key.shift = false;
							e.preventDefault();
							break;
						case 38: // space
							key.up = false;
							e.preventDefault();
							break;
					}
				}, false);

				window.addEventListener('resize', function (e) {
					setDimensions();
				}, false);

				canvas.addEventListener('mousedown', function (e) {
					press = true;
				}, false);

				document.addEventListener('mouseup', function (e) {
					press = false;
				}, false);

				canvas.addEventListener('mousemove', function (e) {
					if (press) {
						mouse = setCoordinates(e);
					}
				}, false);

				// @TODO: add touch events

			}

		};

	})();

	// Create new particles
	var Particle = function (canvas) {

		var range = Math.random() * 180 / Math.PI, // random starting point
			spread = canvas.height, // how far away from text should the particles begin?
			size = Math.random() * 7; // random size of particle

		this.delta = 0.25;
		this.x = 0;
		this.y = 0;

		// starting positions
		this.px = (canvas.width / 2) + (Math.cos(range) * spread);
		this.py = (canvas.height / 2) + (Math.sin(range) * spread);

		this.velocityX = Math.floor(Math.random() * 10) - 5;
		this.velocityY = Math.floor(Math.random() * 10) - 5;

		this.size = size;
		this.origSize = size;

		this.inText = false;

	};

	var FPS = {

		// defaults
		delta: 0,
		lastTime: 0,
		frames: 0,
		totalTime: 0,
		updateTime: 0,
		updateFrames: 0,

		initialize: function (canvasID, fpsID) {
			this.lastTime = (new Date()).getTime();
			if (!document.getElementById(fpsID) && document.getElementById(canvasID)) {
				this.createFPS(canvasID, fpsID);
			}
		},

		// create FPS div if needed
		createFPS: function (canvasID, fpsID) {
			var div = document.createElement('div');
			div.setAttribute('id', fpsID);
			var canvas = document.getElementById(canvasID);
			var parent = canvas.parentNode;
			div.innerHTML = "FPS AVG: 0 CURRENT: 0";
			parent.appendChild(div);
		},

		// update FPS count
		update: function (fpsID) {
			var now = (new Date()).getTime();
			this.delta = now - this.lastTime;
			this.lastTime = now;
			this.updateTime += this.delta;
			this.totalTime += this.delta;
			this.frames++;
			this.updateFrames++;
			document.getElementById(fpsID).innerHTML = "FPS Average: " + Math.round(1000 * this.frames / this.totalTime) + " Current: " + Math.round(1000 * this.updateFrames / this.updateTime);
			this.updateTime = 0; // reset time
			this.updateFrames = 0; // reset frames
		}

	};

	Clock.init('tit');
</script> -->

</html>